package com.onec.service.route.service.base.impl;


import cn.hutool.core.date.DateUtil;
import com.onec.service.api.content.RedisKeyContent;
import com.onec.service.api.dto.request.route.RouteReq;
import com.onec.service.api.enums.error.RouteErrorEnum;
import com.onec.service.api.exception.RouteException;
import com.onec.service.api.utils.RedisKeyUtil;
import com.onec.service.route.entity.TradeRuleInfo;
import com.onec.service.route.service.base.BaseTradeConfigDefaultService;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.Optional;

/**
 * 商户交易金额,笔数限制：单笔金额，单日金额，月金额。限制笔数：
 *
 * @author onec
 * @see com
 * @since 20210105
 */
@Service(value = "MERCHANT_AMOUNT_LIMIT_SERVICE")
public class MerchantAmountLimitServiceImpl extends BaseTradeConfigDefaultService {


    /**
     * 交易业务类处理：交易上送之前检验是否符合条件：
     *
     * @param ruleParam tradeRuleInfo
     * @return ResponseMerchant
     */
    @Override
    public boolean beforeExecute(RouteReq ruleParam, TradeRuleInfo tradeRuleInfo) {
        // 交易规则不存在当作成功;
        if (Optional.ofNullable(tradeRuleInfo.getValue()).isEmpty()) {
            return false;
        }
        // 交易规则配置：单笔金额：0 ；禁止交易
        String[] ruleValue = tradeRuleInfo.getValue().split(",");
        BigDecimal amount = ruleParam.getAmount();
        // 单笔限额;
        BigDecimal ruleAmount = new BigDecimal(ruleValue[0]);
        if (amount.compareTo(ruleAmount) > 0) {
            throw new RouteException(RouteErrorEnum.MERCHANT_PRODUCT_AMOUNT_LIMIT, ruleAmount.toPlainString());
        }

        Date date = DateUtil.date();

        String dayTime = DateUtil.format(date, "yyyy-MM-dd");
        String merchantDayKey = RedisKeyUtil.getKey(dayTime, ruleParam.getProduct(), ruleParam.getMerchantNo());
        // 日限额
        BigDecimal dayRuleAmount = new BigDecimal(ruleValue[1]);
        this.checkDayLimitAmount(merchantDayKey, RedisKeyContent.DAY_AMOUNT, amount, dayRuleAmount);

        // 日笔数限制：
        double dayCount = Double.valueOf(ruleValue[3]);
        this.checkDayLimitCount(merchantDayKey, RedisKeyContent.DAY_COUNT, dayCount);


        String monthTime = DateUtil.format(date, "yyyy-MM");
        String merchantMonthKey = RedisKeyUtil.getKey(monthTime, ruleParam.getProduct(), ruleParam.getMerchantNo());
        // 月限额
        BigDecimal monthRuleAmount = new BigDecimal(ruleValue[2]);
        this.checkMonthLimitAmount(merchantMonthKey, RedisKeyContent.MONTH_AMOUNT, amount, monthRuleAmount);
        // 月笔数限制：
        double monthCount = Double.valueOf(ruleValue[4]);
        this.checkMonthLimitCount(merchantMonthKey, RedisKeyContent.MONTH_COUNT, monthCount);

        return false;
    }

    /**
     * 交易处理成功：添加相对应的数据。
     *
     * @param
     * @return ResponseOnline
     */
    @Override
    public boolean afterExecute(RouteReq ruleParam) {

        Date date = DateUtil.date();
        String dayTime = DateUtil.format(date, "yyyy-MM-dd");

        long timeOut = RedisKeyUtil.getExpireTime();
        // 添加日累计金额：日累计笔数：
        String dayLimitSumKey = RedisKeyUtil.getKey(dayTime, ruleParam.getProduct(), RedisKeyContent.DAY_AMOUNT);
        this.addLimit(dayLimitSumKey, ruleParam.getMerchantNo(), Double.valueOf(ruleParam.getAmount().toString()), timeOut);

        // 日累计笔数
        String dayLimitCntKey = RedisKeyUtil.getKey(dayTime, ruleParam.getProduct(), RedisKeyContent.DAY_COUNT);
        this.addLimit(dayLimitCntKey, ruleParam.getMerchantNo(), 1.0, timeOut);

        // 月累计金额，月累计笔数
        String monthTime = DateUtil.format(date, "yyyy-MM");
        String monthLimitSumKey = RedisKeyUtil.getKey(monthTime, ruleParam.getProduct(), RedisKeyContent.MONTH_AMOUNT);
        this.addLimit(monthLimitSumKey, ruleParam.getMerchantNo(), Double.valueOf(ruleParam.getAmount().toString()), 0);

        // 月累计笔数
        String monthLimitCntKey = RedisKeyUtil.getKey(monthTime, ruleParam.getProduct(), RedisKeyContent.MONTH_COUNT);
        this.addLimit(monthLimitCntKey, ruleParam.getMerchantNo(), 1.0, 0);
        return false;
    }

}
